package it.univpm.diiga.semanticsearch.configurazione;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;




public class Configuration {

	 private static String configRemoteURL="http://test.enfixweb.it/config.xml"; //URL FILE DI CONFIGUARAZIONE
	 private static String configLocalURL="config/localConfig.xml"; //URL FILE DI CONFIGUARAZIONE
	 
	 private static List<URL> publicRepoLink;
	 private static List<URL> defaultRepoLink;
	 private static List<URL> localRepoLink;
	 private static List<File> localRepoFile;
	 
	 private static Hashtable<String, Object> configuration = new Hashtable<String, Object>();
	
	 public static List<URL> getDefaultRepoLink(){
		   return (List<URL>) configuration.get("defaultRepoLink");
	   }
	 
	 public static List<URL> getPublicRepoLink(){
		 return (List<URL>) configuration.get("publicRepoLink");
	 }
	 
	 public static File getLocalRepoLink(){
		 			 
		 return new File((String) configuration.get("localRepoLink"));
	 }
	 
	 public static String getLocalRepoFormat(){
		 return (String) configuration.get("formatLocalRepository");
	 }
	 
	 
	 public static Hashtable getConfiguration(){
		   return configuration;
	   }
	 
	 public static boolean isSetProxy(){
		 if (configuration.get("proxyEnabled").toString().equalsIgnoreCase("yes")){
			 return true;
		 }
		 return false;
	 }
	 
	 public static Hashtable getAllConfiguration() throws Exception{
		  boolean remoteconfig=findRemoteConfiguration();
		   boolean localconfig=findLocalConfiguration();
		   
		   if ( remoteconfig && localconfig)
			   throw new FileConfigExc();
		   if (remoteconfig)
			   throw new RemoteExc();
		   if (localconfig)
			   throw new LocalExc();
		   return configuration;
	   }
	
	 
	
	 
	 
	public static boolean findRemoteConfiguration() throws  Exception{
		  // Document document=null;
			publicRepoLink=new ArrayList<URL>();
			defaultRepoLink=new ArrayList<URL>();
			
		   boolean repoexc=false;
		   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
		   try{
				DocumentBuilder db = dbf.newDocumentBuilder();
			
				URL url = new URL(configRemoteURL);
				URLConnection uc=url.openConnection();
				uc.setConnectTimeout(10000);
				uc.connect();
				//InputStream inputStream = url.openStream();
				InputStream inputStream =null;
				
						inputStream = uc.getURL().openStream();
						
						
						Document document = db.parse(inputStream);
						inputStream.close();
						Element rootEle = document.getDocumentElement(); //config
						
						//RECUPERO REPOSITORY
						NodeList list_serv = rootEle.getElementsByTagName("repository");
						if (list_serv.getLength()==0){
							return true;
						}
						for(int i = 0 ; i < list_serv.getLength();i++) {
		
							Element service = (Element)list_serv.item(i);
				            
							
							NodeList list_ele = service.getElementsByTagName("public");
				            if(list_ele != null && list_ele.getLength() > 0) {
				                Element ele = (Element)list_ele.item(0);
				                if (ele.hasChildNodes()){ // if node exist
				                 publicRepoLink.add(new URL(ele.getFirstChild().getNodeValue())); //link public
				                 //System.out.println(this.publicRepoLink.get(i).toString());
				     			configuration.put("publicRepoLink", publicRepoLink);
				     			
				                }
				               
				            }
				            else{
				            	 repoexc=true;
				            	 
				            }
				            
				            list_ele = service.getElementsByTagName("default");
				            if(list_ele != null && list_ele.getLength() > 0) {
				            	for (int j=0; j<list_ele.getLength(); j++){
				            		Element ele = (Element)list_ele.item(j);
				            		if (ele.hasChildNodes()){ // if node exist
				            			defaultRepoLink.add(new URL(ele.getFirstChild().getNodeValue()));
				            			//System.out.println(this.defaultRepoLink.get(j).toString());
				            			//configuration.put("defaultRepoLink", defaultRepoLink);
		
				            		}
				            	}
				            	configuration.put("defaultRepoLink", defaultRepoLink);
				            }else{
				            	repoexc=true;
				            	
				            }
				            	  		 
						}
						
						
						/*if (repoexc)
							throw new RemoteExc();*/
				}catch(Exception e){
					System.out.println("remote exc");
					throw new RemoteExc();
				}
				return repoexc;
		   
	   }
	   
	   public static boolean findLocalConfiguration() throws Exception{
		   localRepoLink=new ArrayList<URL>();
			localRepoFile=new ArrayList<File>();
		   boolean proxyexc=false;
		  
		   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
			
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document document=null;
			//try{
					document = db.parse(new File(configLocalURL));
			   		
					Element rootEle = document.getDocumentElement(); //config
				   
					
				   
				 //RECUPERO PROXY INFO
					NodeList proxy_setting = rootEle.getElementsByTagName("proxy");
					if (proxy_setting.getLength()==0){
						return true;
					}
					for(int i = 0 ; i < proxy_setting.getLength();i++) {
		
						Element service = (Element)proxy_setting.item(i);
			           
						
					   NodeList list_ele = service.getElementsByTagName("address");
			           if(list_ele != null && list_ele.getLength() > 0) {
			               Element ele = (Element)list_ele.item(0);
			               if (ele.hasChildNodes()){ // if node exist
			               	configuration.put("proxyAddress", ele.getFirstChild().getNodeValue());
			               }
			               else
			            	   configuration.put("proxyAddress", "");
			           }
			           else{
			        	   proxyexc=true;
			           }
			           
			           list_ele = service.getElementsByTagName("port");
			           if(list_ele != null && list_ele.getLength() > 0) {
			           	for (int j=0; j<list_ele.getLength(); j++){
			           		Element ele = (Element)list_ele.item(j);
			           		if (ele.hasChildNodes()){ // if node exist
			           			configuration.put("proxyPort", ele.getFirstChild().getNodeValue());
			           			
			           		} else
			           			configuration.put("proxyPort", "");
			           	}
			           }
			           else{
			        	   proxyexc=true;
			           }
			           
			           list_ele = service.getElementsByTagName("enabled");
			           if(list_ele != null && list_ele.getLength() > 0) {
			           	for (int j=0; j<list_ele.getLength(); j++){
			           		Element ele = (Element)list_ele.item(j);
			           		if (ele.hasChildNodes()){ // if node exist
			           			configuration.put("proxyEnabled", ele.getFirstChild().getNodeValue());
			           			if (ele.getFirstChild().getNodeValue().equalsIgnoreCase("yes")){
			           				System.getProperties().put( "proxySet", "true" );
			           				String address= configuration.get("proxyAddress").toString();
			           				String port=configuration.get("proxyPort").toString();
			           				if (!proxyexc){
			           					System.getProperties().put( "proxyHost", configuration.get("proxyAddress").toString() );
			           					System.getProperties().put( "proxyPort", configuration.get("proxyPort").toString());
			           				}
			           			}else{
			           				System.getProperties().put( "proxySet", "false" );
			           				System.getProperties().put( "proxyHost", "" );
		           					System.getProperties().put( "proxyPort", "");
			           			}
			           		}
			           	}
			           }
			           else{
			        	  proxyexc=true;
			           }
			                       		 
					}
					
					
					//RECUPERO LOCAL REPO SETTINGS
					NodeList repository_setting = rootEle.getElementsByTagName("repository");
					if (repository_setting.getLength()==0){
						return true;
					}
					for(int i = 0 ; i < repository_setting.getLength();i++) {
		
						Element service = (Element)repository_setting.item(i);
			           
						
					   NodeList list_ele = service.getElementsByTagName("link");
					   
					   
					   
					   
			           if(list_ele != null && list_ele.getLength() > 0) {
			               Element ele = (Element)list_ele.item(0);
			               if (ele.hasChildNodes()){ // if node exist
			                	File file=new File(ele.getFirstChild().getNodeValue());
			                	if (!file.exists()){
			                		proxyexc=true;
			                		configuration.put("localRepoLink","");
			                	}else{
			                		configuration.put("localRepoLink",file.getAbsolutePath());
			                	}
			               }
			               else{
			            	   configuration.put("localRepoLink","");
			               }
			           }
			           else{
			        	   proxyexc=true;
			           }
			           
			           list_ele = service.getElementsByTagName("format");
			           if(list_ele != null && list_ele.getLength() > 0) {
			           	for (int j=0; j<list_ele.getLength(); j++){
			           		Element ele = (Element)list_ele.item(j);
			           		if (ele.hasChildNodes()){ // if node exist
			           			configuration.put("localRepoFormat", ele.getFirstChild().getNodeValue());
			           			
			           		}
			           		else{
			           			configuration.put("localRepoFormat","xml");
			           		}
			           	}
			           }
			           else{
			        	   proxyexc=true;
			           }
			                       		 
					}
			/*}catch(Exception e){
	   			System.out.println("local exc");
	   			throw new LocalExc();
	   		}*/
			
			return proxyexc; 

	   }
	
	   
	   public static void setNewConfiguration(String parentTag,String parameterTag,String value) throws Exception{
		   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
			DocumentBuilder db = dbf.newDocumentBuilder();
			File file=new File(configLocalURL);
		    Document document = db.parse(file);
		   Element rootEle = document.getDocumentElement();
		    //int paraSize=para.length;
			NodeList list_serv = rootEle.getElementsByTagName(parentTag);
			for(int i = 0 ; i < list_serv.getLength();i++) {

				Element service = (Element)list_serv.item(i);

					NodeList list_ele = service.getElementsByTagName(parameterTag);
		            if(list_ele != null && list_ele.getLength() > 0) {
		               Element ele = (Element)list_ele.item(0);
		               if (ele.hasChildNodes()){ // if node exist
		            	   if (value.equals("") || value==null)
		            		   ele.getFirstChild().setNodeValue("");
		            	   else
		            		   
		            		   //if we are setting a new local repository
		            		   if (parameterTag.equals("link")){
		        
		            			   File localRepo = new File(value);
		            			 	// if  the repository file doesn't exist
		            				 if (!localRepo.exists()) {
		            					  int response = JOptionPane.showConfirmDialog(null, "Selected Local Repository doesn't exist.\n"+
		            							  "Do you want to create a new empty Repository?", "Settings",
		            						        JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
		            						    if (response == JOptionPane.YES_OPTION) {
		            								 createNewRepo(value);
		            					        } 
		            				 }

		            		   }
		            		   ele.getFirstChild().setNodeValue(value);
		               }
		               else{
		            	   ele.setTextContent(value);
		  
		               }
		           }
			
	       
	                      		 
			}
			
			   //setting up a transformer
		    TransformerFactory transfac = TransformerFactory.newInstance();
		    Transformer trans = null;
			try {
				trans = transfac.newTransformer();
			} catch (TransformerConfigurationException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
		 
		    //generating string from xml tree
		    StringWriter sw = new StringWriter();
		    StreamResult result = new StreamResult(sw);
		    DOMSource source = new DOMSource(document);
		    try {
				trans.transform(source, result);
			} catch (TransformerException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		    String xmlString = sw.toString();
			
			OutputStream f0 = null;
			byte buf[] = xmlString.getBytes();
		    try {
		    	/*URL url;
				url = new URL(this.configLocalURL);
				URLConnection uc=url.openConnection();
				uc.setConnectTimeout(10000);
				uc.connect();*/
				f0 = new FileOutputStream(file);
				 for(int i=0;i<buf .length;i++) {
					 	f0.write(buf[i]);
					    }
						f0.close();
						buf = null;
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		   
	   }
	   
	   
	   private static void createNewRepo(String link){
		   	
		   File localRepo = new File(link);

			 try {
				 // creates a new blank repository
				 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();	
				 DocumentBuilder db = dbf.newDocumentBuilder();
				 Document document=dbf.newDocumentBuilder().newDocument();
		     		document.appendChild(document.createElement("repository"));
			
		     	localRepo.createNewFile();//creates an empty file at the localrepolink
				
		     	//write the new blank repository to file
					Source source = new DOMSource(document); 
					Result result = new StreamResult(localRepo);
					
					Transformer xformer = TransformerFactory.newInstance().newTransformer(); 
					xformer.transform(source, result); 
					} catch(Exception ex){}
			
		   
	   }
	   
	   
	   
	   
	   /*
	    * ECCEZIONI
	    */
	  
	   
	   public static class RemoteExc extends FileConfigExc {

			public RemoteExc() {

		    }
		    public String toString() {
		        return getMessage();
		    }
		}
	   
	   
	   public static class FileConfigExc extends Exception {
		    public FileConfigExc() {

		        super("Impossibile trovare il repository di default");
		    }
		    public String toString() {
		        return getMessage();
		    }
		}
	   public static class LocalExc extends FileConfigExc {
		    public LocalExc() {

		    }
		    public String toString() {
		        return getMessage();
		    }
		}
	
}
